#!/bin/bash
current_path=/usr/bin
config_path=/etc/a-fot

# Profile名字
profile_name="profile.data"
# gcov名字
gcov_name="profile.gcov"
# Wrapper所在路径
fake_gcc_path="${current_path}/fake_gcc_path/"
mkdir -p ${fake_gcc_path}

# 解析配置文件配置项
function parse_config() {
  is_file_exist "${config_path}/a-fot.ini"
  while read line; do
    if [[ ! ${line} =~ "#" ]]; then
      key=$(echo ${line} | awk -F "=" '{print $1}')
      value=$(echo ${line} | awk -F "=" '{print $2}')
      eval "${key}=${value}"
    fi
  done <${config_path}/a-fot.ini
}

# 解析输入的参数
function parse_input_params() {
  if [[ $# == 1 ]]; then
    suggest_info
    exit 1
  fi
  while [ $# -ge 2 ]; do
    case $1 in
    --opt_mode)
      opt_mode=$2
      shift 2
      ;;
    --perf_time)
      perf_time=$2
      shift 2
      ;;
    --app_name)
      application_name=$2
      shift 2
      ;;
    --app_source_path)
      application_source_path=$2
      shift 2
      ;;
    --bin_file)
      bin_file=$2
      shift 2
      ;;
    --app_make_file)
      application_make_file=$2
      shift 2
      ;;
    --work_path)
      work_path=$2
      shift 2
      ;;
    --benchmark_file)
      benchmark_file=$2
      shift 2
      ;;
    --max_waiting_time)
      max_waiting_time=$2
      shift 2
      ;;
    --gcc_path)
      gcc_path=$2
      shift 2
      ;;
    *)
      suggest_info
      exit 1
      ;;
    esac
  done
}

function suggest_info() {
  echo """
Usage: /bin/bash a-fot.sh [OPTION...]

--opt_mode    Optimization modes (AutoFDO、AutoPrefetch、AutoBOLT)
--perf_time    Perf sampling duration (unit: seconds)
--gcc_path    gcc path
--app_name    application process name
--app_source_path    Application source code path
--bin_file    Executable after binary installation
--app_make_file    App build script path
--work_path    Script working directory (used to compile the application to store the profile)
--benchmark_file    Benchmark path and run command
--max_waiting_time    Maximum binary startup time (unit: seconds)
"""
}

# 根据模式加载不同的优化脚本
function load_script() {
  case ${opt_mode} in
  "AutoFDO")
    source ${current_path}/auto_fdo.sh
    ;;
  "AutoPrefetch")
    source ${current_path}/auto_prefetch.sh
    ;;
  "AutoBOLT")
    source ${current_path}/auto_bolt.sh
    ;;
  *)
    echo "[ERROR] Optimization mode ${opt_mode} is not supported, Check the configuration item: opt_mode."
    exit 1
    ;;
  esac
}

# 公共依赖检查项
function check_common_dependency() {
  if ! rpm -q perf &>/dev/null; then
    echo "[ERROR] Optimization mode ${opt_mode} but perf is missing, try 'yum install perf'"
    exit 1
  fi
}

# 使用原始编译选项进行编译
function old_compilation() {
  echo "[INFO] Start raw compilation"
  is_file_exist ${application_make_file} "application_make_file"
  /bin/bash ${application_make_file}
  is_success $?
}

# 创建profile空文件
function create_profile() {
  now_time=$(date '+%Y%m%d-%H%M%S')
  profile_data_path=${work_path}/${now_time}
  if [[ ! -d ${profile_data_path} ]]; then
    mkdir -p ${profile_data_path}
  fi
  echo "[INFO] Path of Profile is: ${profile_data_path}/${profile_name}"
}

# 创建wrapper之后的操作
function post_create_wrapper() {
  chmod 755 ${fake_gcc_path}/gcc
  chmod 755 ${fake_gcc_path}/g++

  export CC=${fake_gcc_path}/gcc
  export CXX=${fake_gcc_path}/g++
  export LD_LIBRARY_PATH=${gcc_path}/lib64:${LD_LIBRARY_PATH}

  export PATH=$(pwd):${PATH}
}

# 执行benchmark脚本
function run_benchmark() {
  echo "[INFO] Start to execute the benchmark."
  process_id=$(pidof ${application_name})
  if [[ -n ${process_id} ]]; then
    echo "[ERROR] Application: ${application_name} process already exists. The benchmark will not be executed. Please check."
    exit 1
  fi
  is_file_exist ${benchmark_file} "benchmark_file"
  /bin/bash ${benchmark_file} &
  is_success $?
}

# 探测应用进程是否存在
function detect_process() {
  echo "[INFO] Start to detect whether process ${application_name} is started."
  detect_time=0
  while [ -z $(pidof ${application_name}) ]; do
    sleep 1
    ((detect_time = ${detect_time} + 1))
    echo "[INFO] Finding ${application_name}"
    if [[ ${detect_time} -gt ${max_waiting_time} ]]; then
      echo "[ERROR] Process ${application_name} is not found after ${max_waiting_time}. Please check."
      exit 1
    fi
  done
  echo "[INFO] Found Process ${application_name}: $(pidof ${application_name})"
}

# 生成新的wrapper后的操作
function post_create_new_wrapper() {
  chmod 755 ${fake_gcc_path}/gcc
  chmod 755 ${fake_gcc_path}/g++
}

# 使用新的编译选项编译
function new_compilation() {
  echo "[INFO] Compile with new compilation options."
  /bin/bash ${application_make_file}
  is_success $?
}

# 判断上一步执行是否成功
function is_success() {
  pre_result=$1
  if [[ ${pre_result} -eq 1 ]]; then
    echo "[ERROR] Execution failed."
    exit 1
  fi
}

# 检查配置文件脚本是否存在
function is_file_exist() {
  file=$1
  config_item=$2
  if [[ ! -f ${file} ]]; then
    if [[ -n ${config_item} ]]; then
      echo "[ERROR] The file ${file} does not exist. Check the configuration item: ${config_item}."
    else
      echo "[ERROR] The file ${file} does not exist."
    fi
    exit 1
  fi
}

#执行入口，部分函数为加载不同优化脚本中得到
function main() {
  parse_config
  parse_input_params "$@"
  load_script
  check_dependency
  create_wrapper
  old_compilation
  run_benchmark
  detect_process
  perf_record
  create_new_wrapper
  new_compilation
}

main "$@"
